package com.example.xcService.pojo.channels.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.xcService.pojo.channels.ChannelService;
import com.example.xcService.pojo.channels.ChannelResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.regex.Pattern;
/**
 * 腾讯官方接口
 * **/
@Slf4j
public class Plugin_ECARD_P004 implements ChannelService {
    public  ChannelResult QueryBalance(JSONObject apiConfig){
        System.out.println("成功调用了QueryBalance");
        return  ChannelResult.success("success");
    }
    public  ChannelResult Submit(JSONObject apiConfig, Map<String,Object> data){
        try {

            String SUPProductId = String.valueOf(data.get("SUPProductId"));
            String[] sls = SUPProductId.split(",");
            String productId = sls.length >= 2 ? sls[0] : SUPProductId;
            String AccountVal=String.valueOf(data.get("AccountVal"));
            BigDecimal price=new BigDecimal(String.valueOf(data.get("PurchasePrice")));

            Map<String,String> dataParams = new LinkedHashMap<>();
            dataParams.put("action","direct_proivde");
            dataParams.put("offer_id",apiConfig.getString("USERID"));
            dataParams.put("product_id",productId);
            dataParams.put("contract_no",apiConfig.getString("ContractNo"));
            dataParams.put("provide_uin",AccountVal);
            dataParams.put("sale_price",price.scaleByPowerOfTen(2).stripTrailingZeros().toPlainString());
            dataParams.put("sub_channel_id","social_e_commerce");
            dataParams.put("user_id","default");
            dataParams.put("user_name","default");
            dataParams.put("user_id_type","default");
            dataParams.put("version","1.0");
            dataParams.put("ts",String.valueOf(Math.toIntExact(System.currentTimeMillis() / 1000)));
            dataParams.put("out_trade_no",String.valueOf(data.get("ChannelOrderCode")));

            if (sls.length >= 2 && !StringUtils.isEmpty(sls[1]) && !"test".equals(sls[1]))
            {
                dataParams.put("activity_id",String.valueOf(sls[1]));
            }
            if (sls.length >= 3)
            {
                dataParams.put("sub_channel_id",String.valueOf(sls[2]));
            }

            if ( Pattern.matches("^[1]([3-9])[0-9]{9}$",AccountVal) == true)
            {
                dataParams.put("provide_no_type","midas_tel_id");
                dataParams.put("action","tob_provide_coupon");
                dataParams.put("provide_uin","86 "+AccountVal);
            }
            else if (Pattern.matches("^[1-9][0-9]{4,10}$",AccountVal) == true)
            {
                dataParams.put("provide_no_type","uin");
            }
            else if (Pattern.matches("^[a-zA-Z]{1}[-_a-zA-Z0-9]{5,19}$",AccountVal) == true)
            {
                dataParams.put("provide_no_type","wx_username");
            }
            if (dataParams.containsKey("provide_no_type") == false)
            {
                return ChannelResult.FAILED("无法识别的充值号");
            }

            String signText=getSignStr(dataParams)+apiConfig.getString("SecretKey");
            String sign= doEncode(KEY_PRIVATE,signText);
            dataParams.put("sig",sign);

            String url=apiConfig.getString("SubmitURL");
            String responseContent = HttpPost(url, dataParams);
            log.info(String.valueOf(data.get("ChannelOrderCode"))+"返回"+responseContent);
            JSONObject retobj = JSONObject.parseObject(responseContent);

            String code=retobj.getString("ret");
            String msg=retobj.getString("msg");
            String errCode=retobj.getString("err_code");

            if("0".equals(code)){
                return ChannelResult.success("充值成功");
            }else  if ("1-503-nginx".equals(errCode)){
                return  ChannelResult.error(errCode+","+msg);
            }else  if ("2066-1003-30202".equals(errCode)){
                return ChannelResult.success("充值成功");
            }
            else {
                return ChannelResult.FAILED(msg);
            }


        } catch (Exception ex) {
            log.error("腾讯提单接口出错:", ex);
            return ChannelResult.error("腾讯提单接口出错");
        }

    }
    public  ChannelResult Query(JSONObject apiConfig,Map<String,Object> data){
        return  ChannelResult.error("无查询接口");

    }

    public  ChannelResult Notify(JSONObject apiConfig,Map<String,Object> data){
        System.out.println("成功调用了Notify");
        return  ChannelResult.success("success");

    }

    public static final String KEY_PRIVATE = "-----BEGIN PRIVATE KEY-----\n" +
            "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCjPxrfu4Gj4MBf\n" +
            "2gToEG8DB6AOs391OcUooGpF+9wvJn3P0hopEpQD2s1sY2OtNedBuyis3G92wHr6\n" +
            "VfAd7MwJJDawy/jJTOFx6ganqUHX8DMjkBIvjQHRUoCfGn4po4xZoeWOnFsxupqh\n" +
            "KCgXCOwAJtwHLvb+SOYhQkeLnr9t+fFfm6M/vuFHwCsFb29Ux4nf4qCEvfYZtE7n\n" +
            "De+EBX9QHTqbnl2c13gLQZ1Ysedq30yzLnlqd0+3YaHpE4k230tQQscghVBUy0dr\n" +
            "jOMJO5FAQzX8//r2+r69mBQotSxpHVWNu/65ZW+mVv6M14KyXM+CtVdp2sdT8LdZ\n" +
            "R6hyUxDXAgMBAAECggEAI8T4Bn33cgkVHeuPl6nCKU/Kam46R11ZLgW4Q41kOZCd\n" +
            "kKPgx48ij5Wp3U4J0TI2cdiomPfUFJkoWSHrcyMnsfkVYrfO04zc+TDmNGaJ3t7q\n" +
            "1agD1Bd5hnwlYrdTXZxQbHNk8VKhSMwyhY1e+20hCQd6vrgztpQSmMcFFjq6h0Yb\n" +
            "VU+78THcKMYtREPW13GASZcE1YJKt2PpLao/EYisuGLGYY54Ty38lzgIIvwThOa1\n" +
            "qeu4YO5u+LnUsRs+hYh4pw5ewBuC/iOrmP7Zdnk0cM+UJE9iiSKBqfcGESG0ZtZ0\n" +
            "BZFfwYvnALq9zR50/iDTX0zL/tcpiM4w+XSGjRHjgQKBgQDSfFQlVsoCMqdS2nFR\n" +
            "CYaFrG53ZRR5qD0ggM+RUft13w6YZqc7RYC8jNlT+U7boC6PXzbuhYvdADs0r5Fu\n" +
            "F+IMwLAOoC003+Cz2dtyEsqjO7rb7zNZcuQaVcWTeBTUEqTgXMybaABpE0pcFQmB\n" +
            "a3+VwUE8RDPI/ZVgmLTWbenY2QKBgQDGi8ys0JujtMm546nrCRKrlHJVrrlQDxVV\n" +
            "u+Vuq/uFW6xkO7l9X6QbYhYmYJhpeYA0HizXQTcJnuQDNPIRaL2rPpVTsoFpTAI4\n" +
            "WlBGOZEcDCmQm3/HunqRW4t6aXa+leKDzyUz6qTor0G3Ae0O4u11FSriUfNJo/Iy\n" +
            "iJGt6AWpLwKBgEhXKqRam7r9pbw4D1IGsBEpHh4yw0K8q6WMH8qWHpJ4Qw/l1/vq\n" +
            "+z/SOK8/s/aPqvDjjIGVrGgcODz3SkhINQyk/N1J97+AYj3t1hnyk2pekO4d28wW\n" +
            "TIcwi2MPljj832Ws/zU6HUn/s0LKiCXOyF6zuLP5zMJ7ROeaFCzOQdyhAoGAPt2f\n" +
            "Fg0Lat9gjEJg1/HMfpWHSkgDlyzfdYEEGXHNNyGayTX7+o2g+aaqGsa1G5iEFnyD\n" +
            "eDjHA33S9oz6JLcEb0dmotS/kyalAVDfYAz0PGxBcO87m3MZQhM5a64fEiOFUHTz\n" +
            "c6fVRXPQm/C5LeB+jXcBWB3YqbWGh6ekcOspd7MCgYEAkYog271k7hZZg6fDMhWf\n" +
            "siTchSIADHOYXOf6MK89WKTdzPB7J4EM4cXfbf3y/tkwGMP2AaecLZJMuADelbvy\n" +
            "a4kjnEePVa81mVXDiOhlXkiqysYIoXjYHShS+O0k68u6gsa/TFiVmpKlusPYA3QH\n" +
            "Bh4oAhb+eETRgwG5cXvfE+8=\n" +
            "-----END PRIVATE KEY-----\n";

    public static String doEncode(String privateKey, String contentToEncode) {
        privateKey = privateKey.replaceAll("-----END PRIVATE KEY-----", "").
                replaceAll("-----BEGIN PRIVATE KEY-----", "").
                replaceAll("\n", "");

        // 私钥需要进行Base64解密
        byte[] b1 = Base64.getDecoder().decode(privateKey);

        try {
            // 将字节数组转换成PrivateKey对象
            PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(b1);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            java.security.Signature privateSignature = java.security.Signature.getInstance("SHA256withRSA");
            privateSignature.initSign(kf.generatePrivate(spec));

            // 输入需要签名的内容
            privateSignature.update(contentToEncode.getBytes("UTF-8"));
            // 拿到签名后的字节数组
            byte[] s = privateSignature.sign();
            // 将签名后拿到的字节数组做一个Base64编码，以便以字符串的形式保存
            return Base64.getEncoder().encodeToString(s);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return "";
    }

    public static String getSignStr(Map<String, String> map) {
        String result = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
            Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {

                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).toString().compareTo(o2.getKey());
                }
            });
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : infoIds) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    String val = item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key +"="+ val+"&");
                    }
                }
            }
            result = sb.toString();
        } catch (Exception e) {
            log.error("获取签名明文出错：", e);
            return null;
        }
        return result;
    }
    public static String HttpPost(String url, Map<String,String> param) {
        String result = "";
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        // 创建Post请求
        HttpPost httpPost = new HttpPost(url);

        // 响应模型
        CloseableHttpResponse response = null;
        try {
            // 设置ContentType(注:如果只是传普通参数的话,ContentType不一定非要用application/json)
            httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
            String sstr="";
            // 参数设置
            List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
            for (Map.Entry<String, String> entry : param.entrySet()) {
                params.add(new BasicNameValuePair( entry.getKey(),
                        entry.getValue()));
                if(entry.getValue().contains("86 ")){
                    sstr = sstr + URLEncoder.encode((String)entry.getKey(), "UTF-8") + "=" +"86%20"+URLEncoder.encode(entry.getValue().replaceAll("86 ","").toString(), "UTF-8") + "&";
                }
                else {
                    sstr = sstr + URLEncoder.encode((String)entry.getKey(), "UTF-8") + "=" + URLEncoder.encode(entry.getValue().toString(), "UTF-8") + "&";
                }
            }
//            UrlEncodedFormEntitys formEntity=new UrlEncodedFormEntitys(params, StandardCharsets.UTF_8);

            httpPost.setEntity(new StringEntity(sstr, StandardCharsets.UTF_8));

            log.info("httpPost请求："+url+"?"+ JSONObject.toJSONString(param));
            // 由客户端执行(发送)Post请求
            response = httpClient.execute(httpPost);
            // 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();

            System.out.println("响应状态为:" + response.getStatusLine());
            if (responseEntity != null) {
                result= EntityUtils.toString(responseEntity);
                log.info("httpPost请求返回："+JSONObject.toJSONString(result));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  result;
    }
}